home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-10-21 | 11.4 KB | 382 lines | [TEXT/KAHL] |
- // Sample code to check out the QuickTime 1.6 transfer proc stuff. Essentially we have a movie that is
- // drawn into a gworld that we create, and our transfer proc should get called after each frame is drawn.
- //
- // This program draws a fram marker on each new frame as the movie is displayed - these markers are
- // essentially just numbers, and come from a marker pict. each marker is 32x32, the pict contains
- // 10 of them and the appropriate marker is copied from the pict to the movie frame.
- //
- // This is not intended as a complete example. For a start the markers are clipped to a circular shape
- // and that is slow, also we use copybits without trying to optimise the frawing. As a consequence you
- // would only expect to see around 8 frames a second for this technique as implemented. With optimisation
- // the Quicktime team have seen rates of up to 30 FPS. To optimise the copybits calls, read the technote
- // “of time and space and copybits”, and use rectangular clipping regions. This snippet illustrates how to
- // draw over a frame of a quicktime movie as the movie is playing.
- //
- // We use set SetTrackGWorld:
- //
- // SetTrackGWorld
- //
- // SetTrackGWorld lets you force a track to draw into a particular GWorld. This
- // GWorld may be different from that of the entire movie. After the track has drawn,
- // it calls your transfer procedure to copy the track to the actual movie GWorld.
- // When your transfer procedure is set, the current GWorld is set to the correct
- // destination. You can also install a transfer procedure and set the GWorld to nil.
- // This results in your transfer procedure being called only as a notification that
- // the track has drawn—no transfer needs to take place.
- //
- // pascal void SetTrackGWorld( Track theTrack,
- // CGrafPtr port,
- // GDHandle gdh,
- // TrackTransferProc proc,
- // long refCon) ;
- //
- // theTrack The track to set the proc to.
- // port The port for the track to draw to, or nil to use the movie’s GWorld.
- // gdh GDevice associated with the port, or nil.
- // proc Returns pointer to your transfer procedure, or nil to remove it.
- // refCon Value to pass to your transfer procedure.
- //
- // typedef pascal OSErr (*TrackTransferProc)(Track t, long refCon);
- //
- // Remember to use the UPP creation procedure - NewTrackTransferProc - when you install the transfer proc,
- // this makes life better on powerpc. If you forget, then you compile native, then the app will crash when
- // the callback is made.
- //
- // Nick Thompson, 10/21/94, AppleLink NICKT
- //
- // Copyright: © 1992-4 by Apple Computer, Inc., all rights reserved.
-
- #include <movies.h>
-
-
- // function prototypes
- Track GetFirstTrackOfType( Movie aMovie, OSType trackType ) ;
- pascal OSErr myTrackTransferProc(Track t, long refCon) ;
- GWorldPtr SetTransferProcsForMovie( Movie aMovie ) ;
-
- OSErr LoadMarkers( GWorldPtr theGWorld ) ;
- void DrawMarker( GWorldPtr theGWorld, Rect *destRect, short index ) ;
-
- //---------------------------------------------------------------------
- // define a structure to hold all the information we need in the transfer
- // proc.
-
- typedef struct {
- GWorldPtr movieGWorld ;
- GWorldPtr trackGWorld ;
- GWorldPtr markerGWorld ; // this holds our markers
- Rect movieRect ;
- } TransferData, *TransferDataPtr, **TransferDataHandle ;
-
-
- enum { kMarkerID = 1000 } ;
- static const short markerWidth = 32 ;
- static const short markerHeight = 32 ;
- static const Rect kMarkerBounds = { 0, 0, 32, 320 } ;
-
- static RgnHandle pMaskRgn = nil ; // the mask region for the frame markers
-
- //---------------------------------------------------------------------
- //
- OSErr LoadMask(void)
- {
- PicHandle thePicture ;
- GWorldPtr savedGWorld ;
- GWorldPtr theGWorld ;
- GDHandle savedDevice ;
- Rect theFrame = {0,0,32,32} ;
- PixMapHandle offPixMap ;
- OSErr theErr ;
-
-
- pMaskRgn = NewRgn() ;
-
- // save our environment
- GetGWorld( &savedGWorld, &savedDevice) ;
-
- // create a small GWorld
- theErr = NewGWorld( &theGWorld, 1, &theFrame, nil, nil, 0L ) ;
-
- // draw into the port we are passed
- SetGWorld( theGWorld, nil ) ;
-
- // get the marker picture
- thePicture = GetPicture( kMarkerID + 1) ;
-
- // there ain't no sanity clause
- if( thePicture == nil )
- return ResError() ;
-
- // image the picture
- DrawPicture( thePicture, &theFrame) ;
-
- // free up the space used temproarily by the picture
- ReleaseResource((Handle)thePicture) ;
-
- // set up the mask region
- offPixMap = GetGWorldPixMap( theGWorld ) ;
- LockPixels(offPixMap) ;
- theErr = BitMapToRegion( pMaskRgn, (BitMap *)*offPixMap ) ;
- UnlockPixels(offPixMap) ;
- OffsetRgn( pMaskRgn, 16, 16 ) ;
-
- // restore the drawing environment
- SetGWorld( savedGWorld, savedDevice) ;
- DisposeGWorld( theGWorld ) ;
- return QDError() ;
-
- }
- //---------------------------------------------------------------------
- //
-
- OSErr LoadMarkers( GWorldPtr theGWorld )
- {
- PicHandle thePicture ;
- GWorldPtr savedGWorld ;
- GDHandle savedDevice ;
- Rect theFrame ;
-
- // save our environment
- GetGWorld( &savedGWorld, &savedDevice) ;
-
- // draw into the port we are passed
- SetGWorld( theGWorld, nil ) ;
-
- // get the marker picture
- thePicture = GetPicture( kMarkerID ) ;
-
- // there ain't no sanity clause
- if( thePicture == nil )
- return ResError() ;
-
- // get the picture frame
- theFrame = (**thePicture).picFrame ;
-
- // image the picture
- DrawPicture( thePicture, &theFrame) ;
-
- // free up the space used temproarily by the picture
- ReleaseResource((Handle)thePicture) ;
-
- // restore the drawing environment
- SetGWorld( savedGWorld, savedDevice) ;
-
- return QDError() ;
- }
-
- //---------------------------------------------------------------------
- // Draw the n'th marker - assumes port is set up
-
- void DrawMarker( GWorldPtr theGWorld, Rect *destRect, short index )
- {
- short offset = 0 ;
- Rect srcRect = {0, 0, 32, 32} ;
- PixMapHandle offPixMap = nil ;
- GrafPtr theCurrentPort ;
-
- // we need this for the copyBits call
- GetPort( &theCurrentPort ) ;
-
- offset = index * markerWidth ;
- srcRect.left += offset ;
- srcRect.right += offset ;
-
- offPixMap = GetGWorldPixMap( theGWorld ) ;
- if( offPixMap ) {
- (void) LockPixels( offPixMap ) ;
-
- // copy from the gWorld Image to the window's port
- CopyBits( (BitMap *)*offPixMap,
- &theCurrentPort->portBits,
- &srcRect,
- destRect,
- srcCopy,
- nil ) ;
-
- // unlock the pixmap
- (void) UnlockPixels( offPixMap ) ;
- }
- }
-
- //---------------------------------------------------------------------
-
- // locate the first track in a movie with the supplied type
- Track GetFirstTrackOfType( Movie aMovie, OSType trackType )
- {
- Track theTrack = nil ;
- OSType mediaType;
- short trackCount ;
- short index ;
-
- trackCount = GetMovieTrackCount(aMovie);
- for ( index=1 ; index <= trackCount ; index++) {
- Track t = GetMovieIndTrack(aMovie, index);
-
- GetMediaHandlerDescription(GetTrackMedia(t), &mediaType, nil, nil);
- if (mediaType == trackType) {
- theTrack = t;
- break;
- }
- }
-
- return theTrack ;
-
- }
-
- //---------------------------------------------------------------------
-
- pascal OSErr myTrackTransferProc(Track t, long refCon)
- {
-
- TransferDataHandle myTDH = (TransferDataHandle)refCon ;
- GrafPtr theNewWorld ;
- GrafPtr movieGWorld ;
- GWorldPtr markerGWorld ;
- PixMapHandle offPixMap ;
- Rect movieBox ;
- static short index = 0 ;
- CGrafPtr savedWorld ;
- GDHandle savedDevice ;
- Str255 theString ;
-
- Rect dstRect = { 16, 16, 48, 48 } ;
-
-
- movieGWorld = (GrafPtr)((**myTDH).movieGWorld) ;
- theNewWorld = (GrafPtr)((**myTDH).trackGWorld) ;
- markerGWorld = (**myTDH).markerGWorld ;
- movieBox = (**myTDH).movieRect ;
-
- offPixMap = GetGWorldPixMap( (GWorldPtr)theNewWorld ) ;
- (void) LockPixels( offPixMap ) ;
-
- GetGWorld( &savedWorld, &savedDevice );
- SetGWorld( (CGrafPtr)theNewWorld, nil ) ;
-
- SetClip( pMaskRgn ) ;
- // ClipRect( &dstRect ) ; // ensure we have the whole area to draw in
- if(++index > 9) index = 0 ; // roll the index around
-
- // draw the next marker over the frame
- DrawMarker( markerGWorld, &dstRect, index ) ;
-
- // MoveTo ( 15, 15 );
- // NumToString ( index++, theString );
- // DrawString ( theString );
-
- // copy the image from the offscreen port
- // into the movies port
-
- SetGWorld( savedWorld, savedDevice ) ;
-
- CopyBits( &theNewWorld->portBits,
- &movieGWorld->portBits,
- &theNewWorld->portRect,
- &movieBox,
- srcCopy,
- nil ) ;
-
- (void) UnlockPixels( offPixMap ) ;
- }
-
- //---------------------------------------------------------------------
-
- Media GetFirstVideoMedia(Movie coolMovie, long *trackIndex)
- {
- Track coolTrack = nil;
- Media coolMedia = nil;
- long numTracks;
- OSType mediaType;
- numTracks = GetMovieTrackCount(coolMovie);
- for (*trackIndex=1; *trackIndex<=numTracks; (*trackIndex)++) {
- coolTrack = GetMovieIndTrack(coolMovie, *trackIndex);
- if (coolTrack) coolMedia = GetTrackMedia(coolTrack);
- if (coolMedia) GetMediaHandlerDescription(coolMedia,
- &mediaType, nil, nil);
- if (mediaType = VideoMediaType) return coolMedia;
- }
- *trackIndex = 0; // trackIndex can't be 0
- return nil; // went through all tracks and no video
- }
-
-
-
- //---------------------------------------------------------------------
-
- short GetFirstVideoTrackPixelDepth(Movie coolMovie)
- {
- SampleDescriptionHandle imageDescH =
- (SampleDescriptionHandle)NewHandle(sizeof(Handle));
- long trackIndex = 0;
- Media coolMedia = nil;
- coolMedia = GetFirstVideoMedia(coolMovie, &trackIndex);
- if (!trackIndex || !coolMedia) return -1; // we need both
- GetMediaSampleDescription(coolMedia, trackIndex, imageDescH);
- return (*(ImageDescriptionHandle)imageDescH)->depth;
- }
-
-
- //---------------------------------------------------------------------
-
- GWorldPtr SetTransferProcsForMovie( Movie aMovie )
- {
-
- Rect trackDimensions = { 0, 0, 0, 0 };
- GWorldPtr theNewWorld ;
- GWorldPtr movieGWorld ;
- GWorldPtr markerGWorld ;
- GDHandle theNewWorldDevice = nil;
-
- Rect markerBounds = kMarkerBounds ;
-
- Fixed height ;
- Fixed width ;
-
- OSErr theErr ;
- Rect movieBox ;
-
- // current environment
- CGrafPtr savedPort ;
- GDHandle savedDevice ;
-
- TransferDataHandle myTDH = (TransferDataHandle)NewHandle( sizeof( TransferData )) ;
- Track aTrack = GetFirstTrackOfType( aMovie, VideoMediaType ) ;
- short trackDepth = GetFirstVideoTrackPixelDepth( aMovie ) ;
-
- if( myTDH == nil || aTrack == nil || trackDepth < 0)
- return ;
-
- GetTrackDimensions( aTrack, &width, &height ) ;
-
- trackDimensions.right = Fix2Long( width );
- trackDimensions.bottom = Fix2Long( height );
-
- // create the marker gWorld - make this the same
- // depth as the track to improve copybits speed
- theErr = NewGWorld( &markerGWorld, trackDepth, &markerBounds, nil, nil, 0L ) ;
- CheckError( theErr, "\pCall to NewGWorld failed" );
-
- // image the marker picts
- LoadMask() ; // this loads our clipping mask - clipping to a mask will give us a performance hit
-
- CheckError( LoadMarkers( markerGWorld ), "\pFailed to load the marker PICT") ; // load the pict containing our 10 numbered
- // circular markers, these are drawn over the frame
-
- (**myTDH).markerGWorld = markerGWorld ;
-
- // create the movie gWorld
- theErr = NewGWorld( &theNewWorld, trackDepth, &trackDimensions, nil, theNewWorldDevice, 0L ) ;
- CheckError( theErr, "\pCall to NewGWorld failed" );
-
- GetMovieGWorld( aMovie, &movieGWorld, nil ) ;
-
- (**myTDH).movieGWorld = movieGWorld ;
- (**myTDH).trackGWorld = theNewWorld ;
-
- GetMovieBox( aMovie, &movieBox ) ;
- (**myTDH).movieRect = movieBox ;
-
- SetTrackGWorld( aTrack, (CGrafPtr)theNewWorld, nil, NewTrackTransferProc( myTrackTransferProc ), (long)myTDH ) ;
-
- }
-